// EnumDirItems.h

#ifndef __ENUM_DIR_ITEMS_H
#define __ENUM_DIR_ITEMS_H

#include "Wildcard.h"
#include "FileFind.h"

#include <vector>
#include <deque>
#include <memory>

namespace Common
{
namespace FileSystem
{

struct CDirItem : public File::CFileInfo
{
  int PhyParent;
  int LogParent;
  
  CDirItem(): PhyParent(-1), LogParent(-1) {}
  CDirItem(const CDirItem& obj) : File::CFileInfo(obj),  PhyParent(obj.PhyParent), LogParent(obj.LogParent)
  {}


  CDirItem& operator=(const CDirItem & obj); 
  CDirItem& operator=(const CFileInfo & obj); 

  bool IsDir() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }

};

class CDirItems
{
	std::deque<CString> Prefixes;
	std::deque<int> PhyParents;
	std::deque<int> LogParents;

  CString GetPrefixesPath(const std::deque<int> &parents, int index, const CString &name) const;
public:
	typedef std::shared_ptr<CDirItem>  PtrItems;
	typedef std::vector<PtrItems> PtrArrayItems;
	PtrArrayItems Items;

  size_t GetNumFolders() const { return Prefixes.size(); }
  CString GetPhyPath(const std::shared_ptr<CDirItem> & item) const;
  CString GetPhyPath(int index) const;
  CString GetLogPath(int index) const;

  size_t AddPrefix(int phyParent, int logParent, const CString &prefix);
  void DeleteLastPrefix();

  void EnumerateDirectory(int phyParent, int logParent, const CString &phyPrefix,
	CStringVector &errorPaths, std::vector<DWORD> &errorCodes);

  void EnumerateDirItems2(
	const CString &phyPrefix,
	const CString &logPrefix,
	const CStringVector &filePaths,
	CStringVector &errorPaths, std::vector<DWORD> &errorCodes);

  void ReserveDown();
};

struct CArcItem
{
  UINT64	Size;
  FILETIME	MTime;
  CString	Name;
  bool		IsDir;
  bool		SizeDefined;
  bool		MTimeDefined;
  bool		Censored;
  UINT32	IndexInServer;
  int		TimeType;
  
  CArcItem(): IsDir(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {}

  CArcItem(const CArcItem & obj) :
	Size(obj.Size),
	MTime(obj.MTime),
	Name(obj.Name),
	IsDir(obj.IsDir),
	SizeDefined(obj.SizeDefined),
	MTimeDefined(obj.MTimeDefined),
	Censored(obj.Censored),
	IndexInServer(obj.IndexInServer),
	TimeType(obj.TimeType)
  {
  }
  CArcItem & operator= (const CArcItem & obj)
  {
	Size = obj.Size;
	MTime = obj.MTime;
	Name = obj.Name;
	IsDir = obj.IsDir;
	SizeDefined = obj.SizeDefined;
	MTimeDefined = obj.MTimeDefined;
	Censored = obj.Censored;
	IndexInServer = obj.IndexInServer;
	TimeType = obj.TimeType;
	  return *this;
  }
};


//void AddDirFileInfo(int phyParent, int logParent,
//	const File::CFileInfo &fi, std::vector<CDirItem> &dirItems);

struct IEnumDirItemCallback
{
  virtual HRESULT ScanProgress(UINT64 numFolders, UINT64 numFiles, const wchar_t *path) = 0;
};

HRESULT EnumerateItems(
	const Wildcard::CCensor &censor,
	CDirItems &dirItems,
	IEnumDirItemCallback *callback,
	CStringVector &errorPaths,
	std::vector<DWORD> &errorCodes);

}
}

#endif
